# 处理依赖数据
# sys.path.append('F:/A_RuanJian/Py_project/imooc/')
from Z_other.unit_for_excel.operation_excel import OperationExcel
from Z_other.unit_for_excel.get_data_ddt import GetData
from jsonpath_rw import parse
from util.operation_json import OperetionJson
from config.file_config import FilePath
from logs.user_log import UserLog
from run_assert.cookie_token import CookieToken
from Z_other.unit_for_excel.col_num import Col_num;col_num = Col_num
from util.operation_yaml import OperationYaml
from run_assert.assert_run import AssertRun
data = GetData()
opera_excel = OperationExcel()
op_json = OperetionJson()
path = FilePath()
log = UserLog().get_log()
op_yaml = OperationYaml()
cookie_key = '__outh'
yaml_key = 'pre_res_value'
assert_run = AssertRun()


class DependdentData:

	# 当前case为前置用例，执行请求，并提取和写入可能会被后面用例需要的值
	def run_pre_case_write(self, sql_id, case_id, pre_key, token, cookies, method, url, request_data_dict, headers, header_type, expect, result_key):
		res = CookieToken().cookie_token(token, cookies, method, url, request_data_dict, headers, header_type)
		res_s = res.json()
		pre_value = self.get_pre_value(pre_key, res_s)
		self.write_pre_value(pre_value, case_id)
		flag, msg = assert_run.assert_main(expect, result_key, res, sql_id)
		return flag, msg

	def write_pre_value(self, pre_value, case_id):
		log.debug('更新依赖数据')
		read_yaml = op_yaml.read_data()
		read_yaml[yaml_key][case_id] = pre_value
		op_yaml.write_data(read_yaml)

	# 尝试先从文件中获取依赖数据
	def get_pre_value_by_file(self, case_id):
		value = op_yaml.read_data()[yaml_key][case_id]
		return value

	# 清除已经使用过的依赖数据
	def delete_pre_value(self, case_id):
		log.debug('清除已经使用过的依赖数据')
		read_yaml = op_yaml.read_data()
		read_yaml[yaml_key][case_id] = None
		op_yaml.write_data(read_yaml)

	# 执行依赖测试，并判断是否需要添加cookie，然后返回结果
	def run_pre(self, case_id, value_list, pre_pre_res_value=None):
		cookies = value_list[col_num.cookie]
		token = value_list[col_num.token]
		method = value_list[col_num.method]
		header_type = value_list[col_num.header_type]
		url_part = value_list[col_num.url]
		url = data.get_request_url_host(url_part,case_id)
		headers_key = value_list[col_num.header]
		headers = data.get_header_for_dict(headers_key)
		data_key = value_list[col_num.data]
		data_dict = data.get_data_for_dict(data_key)
		if pre_pre_res_value :
			pos_key = value_list[col_num.pos_key]
			data_dict = self.get_pre_data_dict(data_dict, pos_key, pre_pre_res_value)
		res = CookieToken().cookie_token(token, cookies, method, url, data_dict, headers, header_type)
		try:
			res_dict = res.json()
		except:
			# res_r = res.text
			res_dict = None
			log.error('错误,依赖接口的响应结果不是dict')
		# log.debug('前置请求 "%s" 的响应结果为：%s；type："%s"' %(pre_case_id, res_r, type(res_r)))
		expect = value_list[col_num.expect]
		result_key = value_list[col_num.result_key]
		pre_assert = assert_run.assert_main_pre(expect, result_key, res, case_id)
		return res_dict, pre_assert

	# 根据依赖的key去获取,并执行依赖测试case的响应,然后返回
	def get_excel_list_by_ID(self, pre_case_id):
		row_num = opera_excel.get_row_num(pre_case_id)
		log.debug('前置请求的case_id为 "%s" ；行号为 "%s"' % (pre_case_id, row_num))
		value_list = data.get_line_data(row_num)
		to_none_list = []
		for i in value_list:
			value = data.to_none(i)
			to_none_list.append(value)
		return value_list


	def get_value_by_key(self,pre_case_id, pre_pre_res_value=None):
		# depend_key = self.data.get_depend_key(row)
		value_list = self.get_excel_list_by_ID(pre_case_id)
		pre_key = value_list[col_num.pre_key]
		res_dict, pre_assert = self.run_pre(pre_case_id, value_list, pre_pre_res_value)
		depend_res_value = self.get_pre_value(pre_key, res_dict)
		return depend_res_value, pre_assert

	def get_pre_value(self, pre_key, response_data):
		log.debug('前置接口的响应结果为: \n%s' % response_data)
		log.debug('前置的key为：%s' % pre_key)
		try:
			male = parse(pre_key).find(response_data)
			depend_res_value = [match.value for match in male][0]
		except:
			print ('错误：依赖数据获取失败')
			log.error('错误：依赖数据获取失败')
		else:
			# print (a01)
			log.debug('获取的value为："%s"；(from前置请求的响应结果中)' %depend_res_value)
			return depend_res_value

	# 获取后置case的key
	def get_pos_data_key(self,key):
		log.debug('后置请求数据的key为"%s"' %key)
		if key == "":
			return None
		elif 'list' in key:
			key_split = key.split(".")
			return int(key_split[1])
		else:
			# 将excel上的依赖key分割，并转格式为int（if 可以转的话）
			# 如 products.0.quantity
			key_split = key.split(".")
			excel_int_list = []
			for i in key_split:
				try:
					int_i = int(i)
				except:
					res = i
				else:
					res = int_i
				excel_int_list.append(res)
			log.debug('后置请求数据的key_list为"%s"' %excel_int_list)
			return excel_int_list

	def get_pre_data(self, pre_case_id, pos_data_dict, pos_data_key):
		log.debug('尝试从文件中获取依赖数据：{}'.format(pre_case_id))
		pre_res_value = self.get_pre_value_by_file(pre_case_id)
		pre_assert = '';pre_assert_02 = ''
		if pre_res_value:
			log.debug('获取依赖数据成功：{}'.format(pre_res_value))
			self.delete_pre_value(pre_case_id)
		else:
			log.debug('获取依赖数据失败，准备从前置请求中获取')
			pre_pre_case_id = self.get_excel_list_by_ID(pre_case_id)[col_num.case_depend_id]
			pre_pre_res_value = None
			if pre_pre_case_id:
				log.debug('该前置请求也需要依赖数据，尝试从文件中获取二层依赖数据：{}'.format(pre_pre_case_id))
				pre_pre_res_value = self.get_pre_value_by_file(pre_pre_case_id)
				if pre_pre_res_value:
					pre_pre_res_value = pre_pre_res_value
					log.debug('获取成功, 二层依赖数据为：{}'.format(pre_pre_res_value))
					self.delete_pre_value(pre_pre_case_id)
				else:
					# log.debug('获取失败，请在excel中让前置请求的依赖请求提前执行！')
					# print('获取失败，请在excel中让前置请求的依赖请求"%s"提前执行！' % pre_pre_case_id)
					log.debug('获取失败，准备执行二层前置请求')
					pre_x3_case_id = self.get_excel_list_by_ID(pre_pre_case_id)[col_num.case_depend_id]
					if pre_x3_case_id:
						print('该二层前置请求需要依赖三层前置请求"%s"，请在excel中先执行三层请求！' % pre_x3_case_id)
					pre_pre_res_value, pre_assert_02 = self.get_value_by_key(pre_pre_case_id)
			else:
				log.debug('前置请求不需要依赖数据，准备发送前置请求')
			# 发起前置请求，并获取返回的依赖key: 获取将key分隔，将list转格式；然后获取list的长度
			log.debug('执行一层前置请求,\n\ncase_id切换为"%s"，执行前置接口' % pre_case_id)
			pre_res_value, pre_assert = self.get_value_by_key(pre_case_id, pre_pre_res_value)
		pos_data_dict = self.get_pre_data_dict(pos_data_dict, pos_data_key, pre_res_value)
		return pos_data_dict, pre_assert, pre_assert_02

	def get_pre_data_dict(self, pos_data_dict, pos_data_key, pre_res_value):
		key_list = self.get_pos_data_key(pos_data_key)
		log.debug('后置请求原始的request_data的类型，值分别为：%s \n%s' % (type(pos_data_dict), pos_data_dict))
		if type(key_list) == int:
			# 当key为int时，把data转换成为list
			data_dict = list(pos_data_dict)
			data_dict[0] = pre_res_value
			return data_dict
		else:
			# 获取数据依赖字段list_key
			try:
				len01 = len(key_list)
				log.debug('key_list的长度为："%s"' % len01)
				# 根据处理后的key数据，更新后置请求的数据，目前支持的索引最大深度为3
				if len01 == 1:
					b01 = key_list[0]
					pos_data_dict[b01] = pre_res_value
				elif len01 == 2:
					# b01 = int_list[0];b02 = int_list[1]
					b01, b02 = key_list
					pos_data_dict[b01][b02] = pre_res_value
				elif len01 == 3:
					# b01 = int_list[0];b02 = int_list[1];b03 = int_list[2]
					b01, b02, b03 = key_list
					log.debug('字符串格式为："%s", "%s"' % (type(b02), b02))
					pos_data_dict[b01][b02][b03] = pre_res_value
				log.debug('更新后的依赖数据为：%s' % pos_data_dict)
			except:
				log.error('依赖数据更新失败！请检查相关参数，还有参数的格式')
			return pos_data_dict


if __name__ == '__main__':
	# print(a01)
	pass



